package com.xdb.sqlparser.builder.impl;

import java.util.List;

import com.xdb.sqlparser.ast.SQLExpr;
import com.xdb.sqlparser.ast.SQLStatement;
import com.xdb.sqlparser.ast.expr.SQLBinaryOperator;
import com.xdb.sqlparser.ast.expr.SQLIdentifierExpr;
import com.xdb.sqlparser.ast.statement.SQLDeleteStatement;
import com.xdb.sqlparser.ast.statement.SQLExprTableSource;
import com.xdb.sqlparser.builder.SQLDeleteBuilder;
import com.xdb.sqlparser.dialect.mysql.ast.statement.MySqlDeleteStatement;
import com.xdb.sqlparser.dialect.oracle.ast.statement.OracleDeleteStatement;
import com.xdb.sqlparser.util.SQLUtils;
import com.xdb.util.JDBCConstants;

public class SQLDeleteBuilderImpl implements SQLDeleteBuilder {

	private SQLDeleteStatement stmt;
	private String dbType;

	public SQLDeleteBuilderImpl(String dbType) {
		this.dbType = dbType;
	}

	public SQLDeleteBuilderImpl(String sql, String dbType) {
		List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);

		if (stmtList.size() == 0) {
			throw new IllegalArgumentException("not support empty-statement :" + sql);
		}

		if (stmtList.size() > 1) {
			throw new IllegalArgumentException("not support multi-statement :" + sql);
		}

		SQLDeleteStatement stmt = (SQLDeleteStatement) stmtList.get(0);
		this.stmt = stmt;
		this.dbType = dbType;
	}

	public SQLDeleteBuilderImpl(SQLDeleteStatement stmt, String dbType) {
		this.stmt = stmt;
		this.dbType = dbType;
	}

	@Override
	public SQLDeleteBuilderImpl limit(int rowCount) {
		throw new UnsupportedOperationException();
	}

	@Override
	public SQLDeleteBuilderImpl limit(int rowCount, int offset) {
		throw new UnsupportedOperationException();
	}

	@Override
	public SQLDeleteBuilder from(String table) {
		return from(table, null);
	}

	@Override
	public SQLDeleteBuilder from(String table, String alias) {
		SQLDeleteStatement delete = getSQLDeleteStatement();
		SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);
		delete.setTableSource(from);
		return this;
	}

	@Override
	public SQLDeleteBuilder where(String expr) {
		SQLDeleteStatement delete = getSQLDeleteStatement();

		SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
		delete.setWhere(exprObj);

		return this;
	}

	@Override
	public SQLDeleteBuilder whereAnd(String expr) {
		SQLDeleteStatement delete = getSQLDeleteStatement();

		SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
		SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, delete.getWhere());
		delete.setWhere(newCondition);

		return this;
	}

	@Override
	public SQLDeleteBuilder whereOr(String expr) {
		SQLDeleteStatement delete = getSQLDeleteStatement();

		SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
		SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, delete.getWhere());
		delete.setWhere(newCondition);

		return this;
	}

	public SQLDeleteStatement getSQLDeleteStatement() {
		if (stmt == null) {
			stmt = createSQLDeleteStatement();
		}
		return stmt;
	}

	public SQLDeleteStatement createSQLDeleteStatement() {
		if (JDBCConstants.ORACLE.equals(dbType)) {
			return new OracleDeleteStatement();
		}

		if (JDBCConstants.MYSQL.equals(dbType)) {
			return new MySqlDeleteStatement();
		}
		return new SQLDeleteStatement();
	}

	public String toString() {
		return SQLUtils.toSQLString(stmt, dbType);
	}
}
